package com.sinping.qh.api.auth;

import com.sinping.qh.api.exception.HandlerException;
import com.sinping.qh.api.support.Const;
import com.sinping.qh.api.support.ConstEum;
import com.sinping.qh.api.support.MediaTypes;
import com.sinping.qh.api.support.ResDto;
import com.sinping.qh.domain.auth.User;
import com.sinping.qh.domain.user.ContentInfo;
import com.sinping.qh.domain.user.UserInfo;
import com.sinping.qh.dto.auth.UserAndResDTO;
import com.sinping.qh.dto.auth.UserDTO;
import com.sinping.qh.dto.auth.UserSessionDTO;
import com.sinping.qh.repository.mongo.user.ContentInfoRepository;
import com.sinping.qh.service.auth.ISessionService;
import com.sinping.qh.service.auth.IUserService;
import com.sinping.qh.utils.mapper.JsonMapper;
import com.sinping.qh.utils.misc.IdGenerator;
import com.sinping.qh.utils.security.CryptoUtil;
import com.sinping.qh.utils.text.TextValidator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author houjiawei
 * @copyright 2017 sinping.com 北京芯平科技股份有限公司. All rights reserved.
 * 本内容仅限于北京芯平科技股份有限公司内部传阅，禁止外泄以及用于其他的商业目的.
 * <p>
 * package com.sinping.woniu.api.auth;
 * /**
 * 前端控制器
 * @create 2017/12/26
 */
@Api(value = "Admin个人管理", description = "Admin个人管理API")
@RequestMapping(value = Const.BASE_URI, name = "个人管理")
@RestController
public class SettingEndPoint {

    @Autowired
    private IUserService userService;

    @Autowired
    @SuppressWarnings("SpringJavaAutowiringInspection")
    private ISessionService sessionService;

    @Autowired
    ContentInfoRepository contentInfoRepository;

    private final static Logger logger = LoggerFactory.getLogger(SettingEndPoint.class);

    /**
     * 获取个人信息
     *
     * @return ResDto
     */
    @ApiParam(name = "token", value = "123412321312")
    @RequestMapping(value = "/setting", method = RequestMethod.GET, name = "获取个人信息")
    @ApiOperation(value = "获取个人信息")
    public ResDto getUserInfo(ServletRequest httpServlet) {

        ResDto resDto = new ResDto(ConstEum.SUCCESS);

        try {
            HttpServletRequest httpServletRequest = (HttpServletRequest) httpServlet;
            String token = httpServletRequest.getHeader("token");

            /***参数为空*/
            if (StringUtils.isBlank(token)) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("msg.login");
                return resDto;
            }
            UserSessionDTO sessionByToken = sessionService.getSessionByToken(token);
            if (sessionByToken != null) {
                String user_id = sessionByToken.getId();
                UserDTO userDTO = userService.loadUserDtoByUserId(user_id);
                if (null == userDTO) {
                    resDto.setStatus(Const.DATA_ERROR);
                    resDto.setMsg("用户不存在");
                    return resDto;
                } else {
                    String userDTOJson = JsonMapper.defaultMapper().toJson(userDTO);
                    resDto.setDatas(userDTOJson);
                    resDto.setStatus(Const.SUCCESS);
                    return resDto;
                }
            } else {
                resDto.setStatus(Const.DATA_ERROR);
                resDto.setMsg("账号不存在");
                return resDto;
            }
        } catch (DataIntegrityViolationException e) {
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            resDto.setStatus(Const.SERVER_ERROR);
            resDto.setMsg(e.getMessage());
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return resDto;
    }

    /**
     * 修改个人信息
     *
     * @param msg
     * @return ResDto
     */
    @ApiOperation(value = "修改个人信息", notes = "参数id必传,nickname:用户全名", consumes = MediaTypes.TEXT_HTML_UTF_8)
    @RequestMapping(value = "/setting", method = RequestMethod.PUT, name = "修改个人信息")
    public ResDto updateById(@ApiParam(name = "msg", value = "{\"id\":\"xxxxxx\",\"nickname\":\"\"}") @RequestParam String msg) {
        ResDto resDto = new ResDto(ConstEum.SUCCESS);
        try {
            User user = JsonMapper.defaultMapper().fromJson(msg, User.class);
            if (user == null) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("参数为空或有不正确的数据格式");
                return resDto;
            }
            if (StringUtils.isBlank(user.getId())) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("用户id不能为空");
                return resDto;
            }
            if (null != user.getNickname() && user.getNickname().length() > 32) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("用户昵称过长");
                return resDto;
            }
            User oldUser = userService.selectById(user.getId());
            if (null == oldUser) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("用户不存在");
            }

            UserInfo one = userService.findMongoUserExist(user);
            if (one == null) {
                return new ResDto(Const.PARAM_ERROR, "用户不存在");
            }

            User updateUser = new User();
            updateUser.setNickname(user.getNickname());
            updateUser.setId(user.getId());
            //更新mongoDB用户信息
            boolean update = userService.updateById(updateUser);
            if (!update) {
                return new ResDto(Const.SERVER_ERROR, "修改失败");
            }

            if (update) {
                one.setFullName(user.getNickname());
                try {
                   userService.updateMongoUserInfo(one);
                } catch (Exception e) {
                    e.printStackTrace();
                    userService.updateById(oldUser);
                    return new ResDto(Const.SERVER_ERROR,"修改信息失败");

                }
            }

        } catch (DataIntegrityViolationException e) {
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            resDto = new ResDto(ConstEum.SERVER_ERROR);
            resDto.setMsg(e.getMessage());
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return resDto;
    }

    @ApiParam(name = "token", value = "123412321312")
    @RequestMapping(method = RequestMethod.GET, value = "/setting/info", name = "同步信息")
    @ApiOperation(value = "同步信息", notes = "用户全名取nickname字段")
    public ResDto settingInfo(ServletRequest httpServlet) {
        ResDto resDto = new ResDto(ConstEum.SUCCESS);
        try {
            HttpServletRequest httpServletRequest = (HttpServletRequest) httpServlet;
            String token = httpServletRequest.getHeader("token");

            /***参数为空*/
            if (StringUtils.isBlank(token)) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("msg.login");
                return resDto;
            }
            UserSessionDTO sessionByToken = sessionService.getSessionByToken(token);
            if (sessionByToken != null) {
                String user_id = sessionByToken.getId();
                UserAndResDTO userAndResDTO = userService.loadUserAndResourceDTO(user_id);
                if (userAndResDTO == null) {
                    resDto.setStatus(Const.DATA_ERROR);
                    resDto.setMsg("用户不存在");
                    return resDto;
                } else {
                    resDto.setStatus(Const.SUCCESS);
                    String userAndResourceDTOStr = JsonMapper.defaultMapper().toJson(userAndResDTO);
                    resDto.setDatas(userAndResourceDTOStr);
                    return resDto;
                }

            } else {
                resDto.setStatus(Const.DATA_ERROR);
                resDto.setMsg("用户不存在");
            }
        } catch (DataIntegrityViolationException e) {
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return resDto;
    }


    /**
     * 用户修改密码
     *
     * @param msg
     * @return ResDto
     */
    @ApiOperation(value = "修改密码", notes = "id，old_content,new_content参数不可为空，且位数与格式正确", consumes = MediaTypes.TEXT_HTML_UTF_8)
    @RequestMapping(value = "/setting/password", method = RequestMethod.PUT, name = "修改密码")
    public ResDto reset(@ApiParam(name = "msg", value = "{\"id\":\"1233\",\"old_content\":\"abc\",\"new_content\":\"\"}") @RequestParam String msg) {

        ResDto resDto = new ResDto(ConstEum.SUCCESS);
        try {
            User user = JsonMapper.defaultMapper().fromJson(msg, User.class);
            if (user == null) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("参数为空或有不正确的数据格式");
                return resDto;
            }
            if (StringUtils.isEmpty(user.getId())) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("用户id不能为空");
                return resDto;
            }
            if (StringUtils.isEmpty(user.getOldContent())) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("旧密码不能为空");
                return resDto;
            }
            if (StringUtils.isEmpty(user.getNewContent())) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("新密码不能为空");
                return resDto;
            }
            User oldUser = userService.selectById(user.getId());
            if (null == oldUser) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("用户不存在");
            }
            UserInfo one = userService.findMongoUserExist(user);
            if (one == null) {
                return new ResDto(Const.SERVER_ERROR, "用户不存在");
            }
            /***验证密码规则*/
            if (!TextValidator.validateContentSimple(user.getNewContent()) || !TextValidator.validateContentSimple(user.getOldContent())) {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("密码格式不正确");
                return resDto;
            }

            ContentInfo contentInfo=contentInfoRepository.findContentInfoByUserId(user.getId());
            String saleStr="";
            if(contentInfo!=null){
                saleStr=contentInfo.getSalt();
            }
            else{
                throw new HandlerException(ConstEum.FAIL,"账号异常,请联系管理员");
            }

            byte[] salt= Base64Utils.decodeFromString(saleStr);


            /*** 旧密码与数据库相同验证通过*/
            if (!oldUser.getContent().equals(CryptoUtil.sha256(salt,user.getOldContent()))) {
                //修改密码时重新生成盐值
                byte[] newSalt=null;
                if(contentInfo!=null){
                    //如果有盐值重新生成盐值
                    newSalt= CryptoUtil.createSalt();
                }
                user.setContent(CryptoUtil.sha256(newSalt,user.getNewContent()));
                boolean update = userService.updateById(user);
                if (!update) {
                    return new ResDto(Const.SERVER_ERROR, "修改失败");
                }
                //更新mongoDB用户信息
                if (update) {
                    one.setContent(user.getContent());
                    try {
                        userService.updateMongoUserInfo(one);
                    } catch (Exception e) {
                        e.printStackTrace();
                        userService.updateById(oldUser);
                        return new ResDto(Const.SERVER_ERROR,"修改失败");
                    }
                }
                if(contentInfo!=null){
                    //修改成功保存盐值
                    contentInfo.setSalt(Base64Utils.encodeToString(newSalt));
                    contentInfo.setGmtModified(new Date());
                    contentInfoRepository.save(contentInfo);
                }
            } else {
                resDto = new ResDto(ConstEum.PARAM_ERROR);
                resDto.setMsg("旧密码错误");
            }
        } catch (DataIntegrityViolationException e) {
            logger.error(e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            resDto = new ResDto(ConstEum.SERVER_ERROR);
            resDto.setMsg(e.getMessage());
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        return resDto;
    }
}
